package com.wenx.hwtest;

import java.util.stream.Stream;

/**
 * 计算1~n中包含1的个数和
 * 输入：12
 * 输出：5 (1包含1个1，11包含2个1，10、12各包含1个1，共计5个1)
 * 要求：代码尽可能简洁、高效
 * Created by wenx on 2019-11-27 14:50
 */
public class DuplicateOne{
    public static void main(String[] args) {
        System.out.println(numberOfoneNum(12));
        System.out.println(numberOfoneNum2(12));
    }

    /**
     * 方法1
     * 整型转字符数组和字符'1'比较
     * @param n
     * @return
     */
    private static int numberOfoneNum(int n) {
        if(n == 0) {
            return 0;
        }
        //从1到n生成连续的整数流
        Stream<Integer> limitNumberStream = Stream.iterate(1, integer -> integer + 1)
                .limit(n);
        int sum = limitNumberStream
                //.parallel()   数据比较大时可并行处理
                .map(Object::toString)  //转换成字符串
                .map(str -> {
                    //字符数组
                    char[] chars = str.toCharArray();
                    int count = 0;
                    //每个字符和1比较统计数量
                    for (char aChar : chars) {
                        if (aChar == '1') {
                            count++;
                        }
                    }
                    return count;
                })
                .mapToInt(Integer::intValue)    // Integer 拆箱成 int
                .sum(); //求和
        return sum;
    }

    /**
     * 方法2
     * 除以10 看余数是否等于1
     * @param n
     * @return
     */
    private static int numberOfoneNum2(int n) {
        if(n == 0) {
            return 0;
        }
        return Stream.iterate(1, integer -> integer + 1)
                .limit(n)
                //.parallel()
                .mapToInt(i -> {
                    int count = 0;
                    //第一步总是会执行，使用do while
                    do{
                        //余数是1，说明存在1
                        if(i % 10 == 1) {
                            count ++;
                        }
                        //高位数降低1位，直到0
                        i = i / 10;
                    } while (i > 0);
                    return count;
                })
                .sum();
    }

}